﻿namespace IBTrader.Modules.Read
{
    using AxTWSLib;
    using IBTrader.Modules.Binarize;
    using IBTrader.Modules.Configuration;
    using IBTrader.Modules.Market;
    using System;
    using System.IO;

    abstract class Reader : IReader
    {
        public event EventHandler<Line> Bid, Ask, Last, Volume, End;
        protected IReaderConfiguration configuration;
        private bool cancel;

        public virtual bool Do(IReaderConfiguration configuration)
        {
            if (configuration.TextFile().Exists && !configuration.BinaryFile().Exists)
                Binarizer.BinarizeFile(configuration.TextFile());

            if (!configuration.BinaryFile().Exists) return false;
            this.configuration = configuration;
            this.cancel = false;

            var reader = new BinaryReader(configuration.BinaryFile().OpenRead());
            var len = reader.BaseStream.Length;
            var pos = 0L;
            var currentDate = configuration.Date.Date;
            var lastTime = -1;

            while (pos < len && !cancel)
            {
                var time = reader.ReadInt32();
                if (time != lastTime) // performance
                {
                    lastTime = time;
                    currentDate = configuration.Date.Date + TimeSpan.FromSeconds(time);
                }
                var price = (double)(decimal)reader.ReadSingle();
                Do(reader, currentDate, price);
                pos += LineSize;
            }

            if (End != null) End(this, new Line { DateTime = currentDate });
            return true;
        }
        protected void Add(TickType tickType, DateTime dateTime, double price)
        {
            var call = Call(tickType);
            if (call != null && Times.InRange(configuration.From, configuration.To, dateTime.TimeOfDay))
                call(this, new Line { DateTime = dateTime, Price = price });
        }
        private EventHandler<Line> Call(TickType tickDate)
        {
            switch (tickDate)
            {
                case TickType.Bid: return Bid;
                case TickType.Ask: return Ask;
                case TickType.Last: return Last;
                case TickType.Volume: return Volume;
                default: return null;
            }
        }
        protected virtual void Do(BinaryReader reader, DateTime date, double price) { throw new NotImplementedException(); }
        protected virtual int LineSize { get { throw new NotImplementedException(); } }
        protected virtual IBinarizer Binarizer { get { throw new NotImplementedException(); } }
        public virtual void Cancel(object _, EventArgs __) { cancel = true; }
        #region real time events
        public virtual void Read(object _, _DTwsEvents_tickPriceEvent e) { }
        public virtual void Read(object _, _DTwsEvents_tickSizeEvent e) { }
        #endregion
    }
}